package com.xiaoshuidi.cloud.module.rooms.framework.rule;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.xiaoshuidi.cloud.framework.common.enums.UserTypeEnum;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.security.core.LoginUser;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.system.api.permission.PermissionApi;
import com.xiaoshuidi.cloud.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 获取用户数据权限
 */
@AllArgsConstructor
@Slf4j
public class EsDeptDataPermissionRule {

    /**
     * LoginUser 的 Context 缓存 Key
     */
    protected static final String CONTEXT_KEY = EsDeptDataPermissionRule.class.getSimpleName();

    private final PermissionApi permissionApi;

    /**
     * 获取用户数据权限的部门ids
     */
    public BoolQueryBuilder permission(BoolQueryBuilder queryBuilder, String deptColumn) {
        // 只有有登陆用户的情况下，才进行数据权限的处理
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return queryBuilder;
        }
        // 只有管理员类型的用户，才进行数据权限的处理
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return queryBuilder;
        }

        // 获得数据权限
        DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
        // 从上下文中拿不到，则调用逻辑进行获取
        if (deptDataPermission == null) {
            deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()).getCheckedData();
            if (deptDataPermission == null) {
                log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
                throw new NullPointerException(String.format("LoginUser(%d)  未返回数据权限",
                        loginUser.getId()));
            }
            // 添加到上下文中，避免重复计算
            loginUser.setContext(CONTEXT_KEY, deptDataPermission);
        }

        // 情况一，如果是 ALL 可查看全部，则无需拼接条件
        if (deptDataPermission.getAll()) {
            return queryBuilder;
        }

        log.info("deptIds: {}", deptDataPermission.getDeptIds());

        // 情况二，即不能查看部门，又不能查看自己，则说明 100% 无权限
        if (CollUtil.isEmpty(deptDataPermission.getDeptIds())
                && Boolean.FALSE.equals(deptDataPermission.getSelf())) {
            QueryBuilder queryBuilder10 = QueryBuilders.termsQuery(deptColumn, Arrays.asList());
            queryBuilder.must(queryBuilder10);
            return queryBuilder;
        }

        // 情况三，拼接 Dept
        QueryBuilder queryBuilder10 = QueryBuilders.termsQuery(deptColumn, deptDataPermission.getDeptIds());
        queryBuilder.must(queryBuilder10);
        return queryBuilder;
    }

}
